package com.thx.common.util;

import org.mindrot.jbcrypt.BCrypt;

import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;

/**
 * 加解密工具.
 *
 * @author balance
 */
public class EncryptUtil {

  private static final String DEFAULT_SALT = "salt";

  /**
   * 使用BCrypt加密，一般用于password加密.
   */
  @Deprecated
  public static String hashBybcrypt(String plaintext) {
    String ciphertext = BCrypt.hashpw(plaintext, BCrypt.gensalt(12));
    return ciphertext;
  }

  /**
   * BCrypt 判断明文是否匹配密文，一般用于判断password是否正确.
   */
  public static boolean checkBybcrypt(String plaintext, String hashed) {
    return BCrypt.checkpw(plaintext, hashed);
  }


  /**
   * md5加密.
   */
  public static final String md5(String plaintext)
      throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String encrypted = new SimpleHash("MD5", plaintext, DEFAULT_SALT, 1).toHex();
    return encrypted;
  }

  /**
   * md5复杂加密，自定义盐、加密次数.
   *
   * @param plaintext 加密文本
   * @param salt 盐，用于密码安全、普通字符串
   * @param hashIterations 加密次数，次数越多越安全、速度越慢
   * @return : md5 散列结果
   */
  public static final String md5(String plaintext, String salt, int hashIterations)
      throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String encrypted = new SimpleHash("MD5", plaintext, salt, hashIterations).toHex();
    return encrypted;
  }


  /**
   * md5加密验证.
   *
   * @param plaintext 未加密文本
   * @param encrypted 已经加密文本
   * @return : 是否匹配
   */
  public static final Boolean checkByMD5(String plaintext, String encrypted)
      throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String md5 = md5(plaintext);
    return md5.equals(encrypted);
  }


  /**
   * md5复杂加密验证，盐和加密次数需要和已加密文本使用的是一致的.
   *
   * @param plaintext 未加密文本
   * @param salt 盐
   * @param hashIterations 加密次数
   * @param encrypted 已加密文本
   * @return : 一致返回 true, 不一致返回 false
   */
  public static final Boolean checkByMD5(String plaintext, String salt, int hashIterations,
      String encrypted) throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String md5 = md5(plaintext, salt, hashIterations);
    return md5.equals(encrypted);
  }

  /**
   * sha-1复杂加密，自定义盐、加密次数.
   *
   * @param plaintext 加密文本
   * @param salt 盐，用于密码安全、普通字符串
   * @param hashIterations 加密次数，次数越多越安全、速度越慢
   * @return : String
   */
  public static final String sha1(String plaintext, String salt, int hashIterations)
      throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String encrypted = new SimpleHash("SHA-1", plaintext, salt, hashIterations).toHex();
    return encrypted;
  }

  /**
   * sha-1加密.
   *
   * @param plaintext 加密文本
   * @return : 加密结果
   */
  public static final String sha1(String plaintext)
      throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String encrypted = new SimpleHash("SHA-1", plaintext, DEFAULT_SALT, 1).toHex();
    return encrypted;
  }


  /**
   * sha-1加密验证.
   *
   * @param plaintext 未加密文本
   * @param encrypted 已加密文本
   * @return : Boolean
   */
  public static final Boolean checkBySha1(String plaintext, String encrypted)
      throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String sha1 = sha1(plaintext);
    return sha1.equals(encrypted);
  }

  /**
   * sha-1复杂加密验证，验证时候的盐、加密次数和已经加密的文本使用的盐、加密次数要一致.
   *
   * @param plaintext 加密文本
   * @param salt 盐
   * @param hashIterations 加密次数
   * @return : Boolean
   */
  public static final Boolean checkBySha1(String plaintext, String salt, int hashIterations,
      String encrypted) throws UnsupportedEncodingException, NoSuchAlgorithmException {
    String sha1 = sha1(plaintext, salt, hashIterations);
    return sha1.equals(encrypted);
  }


  /**
   * bcrypt加密.
   *
   * @param plaintext 加密文本
   * @return : String
   */
  public static final String bcrypt(String plaintext) {
    String ciphertext = BCrypt.hashpw(plaintext, BCrypt.gensalt(12));
    return ciphertext;
  }

  /**
   * DES加密, 可逆的校验密码.
   *
   * @param plaintext 未加密文本
   * @param hashed 已加密文本
   */
  public static boolean checkByDes(String plaintext, String hashed) throws Exception {
    return plaintext.equals(EncrypDesUtil.decryption(hashed));
  }
}
